package com.zyx.concurrentdemo.c06cas;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @author Yaxi.Zhang
 * @since 2021/10/18 10:39
 * desc: 使用 AtomicStampedReference 解决 ABA 问题
 */
@Slf4j(topic = "c.TestAbaAtomicStampedReference")
public class TestAbaAtomicStampedReference {

    static AtomicStampedReference<String> ref = new AtomicStampedReference<>("A", 0);

    public static void main(String[] args) throws InterruptedException {
        log.debug("main start...");
        int stamp = ref.getStamp();
        other();
        TimeUnit.SECONDS.sleep(2);
        // 修改之前除了需要内容未修改, 还需要保证版本号一致
        log.debug("stamp:{}, change A->C {}", stamp, ref.compareAndSet("A", "C", stamp, stamp + 1));
    }

    private static void other() throws InterruptedException {
        new Thread(() -> {
            int stamp = ref.getStamp();
            log.debug("stamp:{}, change A->B {}", stamp, ref.compareAndSet("A", "B", stamp, stamp + 1));
        }, "t1").start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(() -> {
            int stamp = ref.getStamp();
            log.debug("stamp:{}, change B->A {}", stamp, ref.compareAndSet("B", "A", stamp, stamp + 1));
        }, "t2").start();
    }

}
